"use strict";

var exports;
if (typeof module === "object" && exports) {
	exports = module.exports;
} else if (typeof window !== "undefined") {
	exports = window["eviltransform"] = {};
}

var earthR = 6378137.0;

function outOfChina(lat, lng) {
	if ((lng < 72.004) || (lng > 137.8347)) {
		return true;
	}
	if ((lat < 0.8293) || (lat > 55.8271)) {
		return true;
	}
	return false;
}

function transform(x, y) {
	var xy = x * y;
	var absX = Math.sqrt(Math.abs(x));
	var xPi = x * Math.PI;
	var yPi = y * Math.PI;
	var d = 20.0 * Math.sin(6.0 * xPi) + 20.0 * Math.sin(2.0 * xPi);

	var lat = d;
	var lng = d;

	lat += 20.0 * Math.sin(yPi) + 40.0 * Math.sin(yPi / 3.0);
	lng += 20.0 * Math.sin(xPi) + 40.0 * Math.sin(xPi / 3.0);

	lat += 160.0 * Math.sin(yPi / 12.0) + 320 * Math.sin(yPi / 30.0);
	lng += 150.0 * Math.sin(xPi / 12.0) + 300.0 * Math.sin(xPi / 30.0);

	lat *= 2.0 / 3.0;
	lng *= 2.0 / 3.0;

	lat += -100.0 + 2.0 * x + 3.0 * y + 0.2 * y * y + 0.1 * xy + 0.2 * absX;
	lng += 300.0 + x + 2.0 * y + 0.1 * x * x + 0.1 * xy + 0.1 * absX;

	return { lat: lat, lng: lng }
}

function delta(lat, lng) {
	var ee = 0.00669342162296594323;
	var d = transform(lng - 105.0, lat - 35.0);
	var radLat = lat / 180.0 * Math.PI;
	var magic = Math.sin(radLat);
	magic = 1 - ee * magic * magic;
	var sqrtMagic = Math.sqrt(magic);
	d.lat = (d.lat * 180.0) / ((earthR * (1 - ee)) / (magic * sqrtMagic) * Math.PI);
	d.lng = (d.lng * 180.0) / (earthR / sqrtMagic * Math.cos(radLat) * Math.PI);
	return d;
}

function wgs2gcj(wgsLat, wgsLng) {
	if (outOfChina(wgsLat, wgsLng)) {
		return { lat: wgsLat, lng: wgsLng };
	}
	var d = delta(wgsLat, wgsLng);
	return { lat: wgsLat + d.lat, lng: wgsLng + d.lng };
}
exports.wgs2gcj = wgs2gcj;
window.wgs2gcj = wgs2gcj

function gcj2wgs(gcjLat, gcjLng) {
	if (outOfChina(gcjLat, gcjLng)) {
		return { lat: gcjLat, lng: gcjLng };
	}
	var d = delta(gcjLat, gcjLng);
	return { lat: gcjLat - d.lat, lng: gcjLng - d.lng };
}
exports.gcj2wgs = gcj2wgs;
window.gcj2wgs = gcj2wgs;

function gcj2wgs_exact(gcjLat, gcjLng) {
	// newCoord = oldCoord = gcjCoord
	var newLat = gcjLat, newLng = gcjLng;
	var oldLat = newLat, oldLng = newLng;
	var threshold = 1e-6; // ~0.55 m equator & latitude

	for (var i = 0; i < 30; i++) {
		// oldCoord = newCoord
		oldLat = newLat;
		oldLng = newLng;
		// newCoord = gcjCoord - wgs_to_gcj_delta(newCoord)
		var tmp = wgs2gcj(newLat, newLng);
		// approx difference using gcj-space difference
		newLat -= gcjLat - tmp.lat;
		newLng -= gcjLng - tmp.lng;
		// diffchk
		if (Math.max(Math.abs(oldLat - newLat), Math.abs(oldLng - newLng)) < threshold) {
			break;
		}
	}
	return { lat: newLat, lng: newLng };
}
exports.gcj2wgs_exact = gcj2wgs_exact;

function distance(latA, lngA, latB, lngB) {
	var pi180 = Math.PI / 180;
	var arcLatA = latA * pi180;
	var arcLatB = latB * pi180;
	var x = Math.cos(arcLatA) * Math.cos(arcLatB) * Math.cos((lngA - lngB) * pi180);
	var y = Math.sin(arcLatA) * Math.sin(arcLatB);
	var s = x + y;
	if (s > 1) {
		s = 1;
	}
	if (s < -1) {
		s = -1;
	}
	var alpha = Math.acos(s);
	var distance = alpha * earthR;
	return distance;
}
exports.distance = distance;

function gcj2bd(gcjLat, gcjLng) {
	if (outOfChina(gcjLat, gcjLng)) {
		return { lat: gcjLat, lng: gcjLng };
	}

	var x = gcjLng, y = gcjLat;
	var z = Math.sqrt(x * x + y * y) + 0.00002 * Math.sin(y * Math.PI);
	var theta = Math.atan2(y, x) + 0.000003 * Math.cos(x * Math.PI);
	var bdLng = z * Math.cos(theta) + 0.0065;
	var bdLat = z * Math.sin(theta) + 0.006;
	return { lat: bdLat, lng: bdLng };
}
exports.gcj2bd = gcj2bd;

function bd2gcj(bdLat, bdLng) {
	if (outOfChina(bdLat, bdLng)) {
		return { lat: bdLat, lng: bdLng };
	}

	var x = bdLng - 0.0065, y = bdLat - 0.006;
	var z = Math.sqrt(x * x + y * y) - 0.00002 * Math.sin(y * Math.PI);
	var theta = Math.atan2(y, x) - 0.000003 * Math.cos(x * Math.PI);
	var gcjLng = z * Math.cos(theta);
	var gcjLat = z * Math.sin(theta);
	return { lat: gcjLat, lng: gcjLng };
}
exports.bd2gcj = bd2gcj;

function wgs2bd(wgsLat, wgsLng) {
	var gcj = wgs2gcj(wgsLat, wgsLng);
	return gcj2bd(gcj.lat, gcj.lng);
}
exports.wgs2bd = wgs2bd;

function bd2wgs(bdLat, bdLng) {
	var gcj = bd2gcj(bdLat, bdLng);
	return gcj2wgs(gcj.lat, gcj.lng);
}
exports.bd2wgs = bd2wgs;


// 计算面积
var earthRadiusMeters = 6371009.0;
var metersPerDegree = 2.0 * Math.PI * earthRadiusMeters / 360.0;
var radiansPerDegree = Math.PI / 180.0;
var degreesPerRadian = 180.0 / Math.PI;
var pointArr;


function calculateArea(points) {
	if (points.length > 2) {
		// var areaMeters2 = PlanarPolygonAreaMeters2(points);  
		// if (areaMeters2 > 1000000.0) {  
		areaMeters2 = SphericalPolygonAreaMeters2(points);
		// alert("面积为" + areaMeters2 + "平方米");  
		// }  
		return areaMeters2
	}
}

exports.calculateArea = calculateArea

/*球面多边形面积计算*/
function SphericalPolygonAreaMeters2(points) {
	var totalAngle = 0;
	for (var i = 0; i < points.length; i++) {
		var j = (i + 1) % points.length;
		var k = (i + 2) % points.length;
		totalAngle += Angle(points[i], points[j], points[k]);
	}
	var planarTotalAngle = (points.length - 2) * 180.0;
	var sphericalExcess = totalAngle - planarTotalAngle;
	if (sphericalExcess > 420.0) {
		totalAngle = points.length * 360.0 - totalAngle;
		sphericalExcess = totalAngle - planarTotalAngle;
	} else if (sphericalExcess > 300.0 && sphericalExcess < 420.0) {
		sphericalExcess = Math.abs(360.0 - sphericalExcess);
	}
	return sphericalExcess * radiansPerDegree * earthRadiusMeters * earthRadiusMeters;
}

/*角度*/
function Angle(p1, p2, p3) {
	var bearing21 = Bearing(p2, p1);
	var bearing23 = Bearing(p2, p3);
	var angle = bearing21 - bearing23;
	if (angle < 0) {
		angle += 360;
	}
	return angle;
}


/*方向*/
function Bearing(from, to) {
	var lat1 = from.lat * radiansPerDegree;
	var lon1 = from.lon * radiansPerDegree;
	var lat2 = to.lat * radiansPerDegree;
	var lon2 = to.lon * radiansPerDegree;
	var angle = -Math.atan2(Math.sin(lon1 - lon2) * Math.cos(lat2), Math.cos(lat1) * Math.sin(lat2) - Math.sin(lat1) * Math.cos(lat2) * Math.cos(lon1 - lon2));
	if (angle < 0) {
		angle += Math.PI * 2.0;
	}
	angle = angle * degreesPerRadian;
	return angle;
}

/*平面多边形面积*/
function PlanarPolygonAreaMeters2(points) {
	var a = 0;
	for (var i = 0; i < points.length; ++i) {
		var j = (i + 1) % points.length;
		var xi = points[i].lon * metersPerDegree * Math.cos(points[i].lat * radiansPerDegree);
		var yi = points[i].lat * metersPerDegree;
		var xj = points[j].lon * metersPerDegree * Math.cos(points[j].lat * radiansPerDegree);
		var yj = points[j].lat * metersPerDegree;
		a += xi * yj - xj * yi;
	}
	return Math.abs(a / 2);
}

function b() {
	var s = "112.523197631836,37.868892669677734;112.5170669555664,37.8605842590332;112.52099609375,37.849857330322266;112.54137420654297,37.8512732521875;112.5351180302734,37.858699798583984";
	var s1 = new Array()
	s1 = s.split(";");
	for (var i = 0; i < s1.length; i++) {
		var ss = s1[i];
		var temp = ss.split(",");
		var point = new Array();
		point.push(Number(temp[0]), Number(temp[1]));
		pointArr.push(point);
	}
	calculateArea(pointArr);
}

const EARTH_RADIUS = 6378137
function toRad(d) { return d * Math.PI / 180; }

var computeArea = function (path) {
	return Math.abs(computeSignedArea(path))
}

var computeSignedArea = function (path) {
	return computeSignedArea(path, EARTH_RADIUS);
}

var computeSignedArea = function (path, radius) {
	let size = path.length;
	if (size < 3) return 0;
	let total = 0;

	let prev = path[size - 1];
	var prevTanLat = Math.tan((Math.PI / 2 - toRad(prev.lat)) / 2)
	let prevLng = toRad(prev.lon)

	path.forEach( function(point){
		let tanLat = Math.tan((Math.PI / 2 - toRad(point.lat)) / 2)
		let Lng = toRad(point.lon)
		total += polarTriangleArea(tanLat, Lng, prevTanLat, prevLng);
		prevTanLat = tanLat;
		prevLng = Lng;
	}
	);
	console.log(Math.abs(total * (EARTH_RADIUS * EARTH_RADIUS)))
	return Math.abs(total * (EARTH_RADIUS * EARTH_RADIUS))
}

var polarTriangleArea = function (tan1, lng1, tan2, lng2) {
	let deltaLng = lng1 - lng2;
	let t = tan1 * tan2;
	return 2 * Math.atan2(t * Math.sin(deltaLng), 1 + t * Math.cos(deltaLng))
}